const userModel = require('../db/user')
const writeErr = require('../utils/writeErr')
const bcryptjs = require('bcryptjs')
const jwt = require('jsonwebtoken')
const path = require('path')
const {readFileSync} = require('fs')
const xy = require('../utils/xy')
const authModel = require('../db/auth')
const roleModel = require('../db/role')
const tidyAuth = require('../utils/tidyAuthList')

module.exports = {
    // 获取用户信息
    async getinfo(req, resp) {
        // 传递来的用户id
        let {userId} = req.params
        // 根据用户id获取用户其他信息
        // 用promise修改数据库操作
        try{
            let docs = await userModel.findOne({_id: userId})
            if(!docs) {
                xy(resp, 405, '用户id有误！')
                return
            }
            xy(resp, 200, '查询成功！', {
                username: docs.username,
                email: docs.email,
                tel: docs.tel,
                createdAt: +new Date(docs.createdAt),
                updatedAt: +new Date(docs.updatedAt)
            })
        }catch(err) {
            writeErr(err)
            xy(resp, 501, '系统繁忙，稍后再试！')
        }
    },
    // 登录
    async login(req, resp) {
        let {username, password} = req.body
        if(!username || !password) {
            xy(resp, 401, '数据不能为空！')
            return
        }
        try{
            // 用promise修改数据库操作
            let docs = await userModel.findOne({username})
            if(!docs) {
                xy(resp, 403, '用户名或密码错误！')
                return
            }
            if(!bcryptjs.compareSync(password, docs.password)) {
                xy(resp, 403, '用户名或密码错误！')
                return
            } 
            // 拼接配置文件路径
            let configFilePath = path.join(__dirname, '../', 'config', 'config.json')
            // 读取配置中的盐
            let salt = JSON.parse(readFileSync(configFilePath, 'utf-8')).tokenSalt
            xy(resp, 200, '登录成功！', {
                token: jwt.sign({
                    userId: docs._id,
                    username: docs.username,
                    startTime: +new Date(),
                    expires: 7200 * 1000
                }, salt),
                userId: docs._id,
                username: docs.username
            })
        }catch(err) {
            writeErr(err)
            xy(resp, 501, '系统繁忙，稍后再试！')
        }
    },
    // 注册处理
    async register(req, resp) {
        let {username, password, email, tel} = req.body
        if(!username || !password || !email || !tel) {
            xy(resp, 401, '数据不能为空！')
            return
        }
        try{
            let docs = await userModel.findOne({username})
            if(docs) {
                xy(resp, 402, '用户名被占用！')
                return
            }
            try{
                docs = await userModel.insertMany({
                    username,
                    password: bcryptjs.hashSync(password, 10),
                    email,
                    tel
                })
                xy(resp, 200, '注册成功！')
            }catch(err) {
                writeErr(err)
                xy(resp, 501, '系统繁忙，稍后再试！')
            }
        }catch(err) {
            writeErr(err)
            xy(resp, 501, '系统繁忙，稍后再试！')
        }
    },
    // 后台 - 用户列表
    async list(req, resp) {
        try{
            let userList = await userModel.find()
            // 深拷贝
            userList = JSON.parse(JSON.stringify(userList))
            // 获取用户的角色
            let promiseArr = []
            // 遍历所有用户
            userList.forEach(user => {
                promiseArr.push(roleModel.findOne({_id: user.role}))
            })
            // 处理所有请求结束
            let PromiseRes = await Promise.all(promiseArr)
            // 遍历所有结果
            PromiseRes.forEach((role, index) => {
                userList[index].role = role
            })
            // 将查询结果放入用户列表中
            xy(resp, 200, '获取用户列表成功', userList.reverse())
        }catch(err) {
            writeErr(err)
            xy(resp, 510, '系统错误')
            return
        }
    },
    // 后台 - 用户登录
    async adminLogin(req, resp) {
        let {username, password} = req.body
        if(!username || !password) {
            xy(resp, 401, '数据不能为空')
            return
        }
        try{
            let user = await userModel.findOne({username})
            if(!user) {
                xy(resp, 410, '账号或密码错误！')
                return
            } 
            let bool = bcryptjs.compareSync(password, user.password)
            if(!bool) {
                xy(resp, 410, '账号或密码错误！')
                return
            }
            if(!user.enable) {
                xy(resp, 411, '账号未启用，请联系管理员！')
                return
            }
            // 获取用户角色id
            let roleId = user.role
            // console.log(111, roleId);
            // 根据角色id查找角色数据
            let role = await roleModel.findOne({_id: roleId})
            // console.log(111, role);
            // 获取角色拥有的所有权限id
            let authArr = role.auths
            // console.log(22, authArr);
            // 根据权限id获取所有权限
            let auths = await authModel.find({_id: {$in: authArr}})
            // console.log(auths);
            // 整理所有权限 - 直接能渲染的格式
            auths = tidyAuth(auths)
            // 拼接配置文件路径
            let configFilePath = path.join(__dirname, '../', 'config', 'config.json')
            // 读取配置中的盐
            let salt = JSON.parse(readFileSync(configFilePath, 'utf-8')).tokenSalt
            xy(resp, 200, '登录成功！', {
                token: jwt.sign({
                    userId: user._id,
                    username: user.username,
                    startTime: +new Date(),
                    expires: 7200 * 1000
                }, salt),
                userId: user._id,
                username: user.username,
                auths
            })
        } catch(err) {
            writeErr(err)
            xy(resp, 511, '系统错误')
            return
        }
    },
    // 后台 - 用户添加
    async adminAdd(req, resp) {
        let {username, password, email, tel, enable, role} = req.body
        if(!username || !password || !email || !tel || enable === undefined || !role) {
            xy(resp, 401, '缺少参数！')
            return
        }
        let user = await userModel.findOne({username})
        if(user) {
            xy(resp, 415, '用户名被占用！')
            return
        }
        password = bcryptjs.hashSync(password, 10)
        try{
            await userModel.insertMany({
                username,
                password,
                email,
                tel,
                enable,
                role
            })
            xy(resp, 200, '用户添加成功！')
        }catch(err) {
            writeErr(err)
            xy(resp, 517, '用户添加失败！')
        }
    },
    // 修改用户状态
    async userStatus(req, resp) {
        let {id} = req.params
        try{
            let user = await userModel.findOne({_id: id})
            try{
                await userModel.updateOne({_id: id}, {enable: !user.enable})
                xy(resp, 200, '状态修改成功!')
            }catch(err) {
                writeErr(err)
                xy(resp, 521, '用户状态修改失败！')
            }   
        }catch(err) {
            writeErr(err)
            xy(resp, 520, '用户查询失败')
        }
        

    },
    // 用户修改
    async userEdit(req, resp) {
        let {id} = req.params
        let {username, password, enable, email, tel, role} = req.body
        // console.log(req.body, id);
        if(!username || !password || enable === undefined || !email || !tel || !role) {
            xy(resp, 501, '缺少参数')
            return
        }
        try{
            await userModel.updateOne({_id: id}, {
                username,
                password: bcryptjs.hashSync(password, 10),
                email,
                tel,
                enable,
                role,
                updatedAt: +new Date()
            })
            xy(resp, 200, '用户修改成功')
        }catch(err) {
            writeErr(err)
            xy(resp, 522, '用户修改失败！')
        }
    },
    async userDel(req, resp) {
        let {id} = req.params
        try{
            await userModel.deleteOne({_id: id})
            xy(resp, 200, '用户删除成功！')
        }catch(err) {
            writeErr(err)
            xy(resp, 523, '用户删除失败！')
        }
    }
}